#ifndef MATROXIMAGINGLIBRARY_H
#define MATROXIMAGINGLIBRARY_H

#include <Mil.h>
#include <QString>
#include <conio.h>
#include <stdlib.h>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QElapsedTimer>

//#define HAVE_INT32
//#include "tiff.h"
#include <NIDAQmx.h>
#include "tiffconf.h"
#include <tiffio.h>
//#include <mainwindow.h>

typedef unsigned char byte;
#define MAX_BUFFERS 32

#define MAX_PROCESSING_BUFFERS      64

#define SUMMATION_BUFFER            0
#define DISK_BUFFER                 1
#define FLIP_CONDITION_BUFFER       2
#define LEFTHALF_BUFFER             3
#define RIGHTHALF_BUFFER            4
#define LEFTCHILD_BUFFER            5
#define RIGHTCHILD_BUFFER           6
#define TEMP1_BUFFER                7

#define LUT0_BUFFER                 8
#define LUT1_BUFFER                 9
#define OVERLAY_BUFFER              10
#define BLOB_FEATURE_LIST              11
#define BLOB_RESULT              12
#define BLOB_OVERLAY              13
#define STAT_RESULT              14
#define HIST_RESULT1               15
#define HIST_RESULT2              16
#define HIST_RESULT3              17
#define HIST_RESULT4              18

#define ROI_CHILDREN8               22

#define HIST_VALUE   65536
//MFTYPE
//MPTYPE


/* User's processing function prototype. */
long __stdcall ProcessingFunction(long HookType, MIL_ID HookId, void MPTYPE *HookDataPtr);

long __stdcall TriggerProcessing(long HookType,  MIL_ID EventId,  void *UserDataPtr);

typedef struct
{
    long    ProcessedImageCount;

    bool    bExtTrigger;
    bool    bRetriggerable;
    bool    bMonitoring;
    bool    bAcquiring;
    bool    bSaveMonitor;
    bool    bAcquire;
    bool    bTriggerWait;
    bool    bFragment;

    int     nSummationCount;
    int     nSummationTotal;
    int     nHorizontalDownsample;

    int     nFramerate;
    int     nTotalFiles;
    int     nGrabbedFrames;
    int     nArchivedFrames;

    int     nSizeX;
    int     nSizeY;
    int     nDesiredLinesPerFrame;

    void *rawframebuffer;
    void *rawframebuffer_todisk;
    void* mMatrox;
    void* mMainWindow;

    QElapsedTimer timer;

} HookDataStruct;

class MatroxImagingLibrary
{
public:
    MatroxImagingLibrary();
    ~MatroxImagingLibrary();

    void Initialize();
    void Shutdown();

    void SetupMILTrigger();
    void SetupIRQTrigger();
    void OpenFile(bool append);
    void CloseFile();
    void StartMonitor();
    void StopMonitor();

    void StartAcquisition();
    void StopAcquisition();
    int InitializeSineCorrect();
    int FreeSineCorrect();
    void SetupFlipConditionBuffer();
    void SetupDCF();
    void FillHookDataStruct();
    void UpdateLUT();
    void UpdateFilename();
    void UpdateGain();
    void UpdateCouplingMode();
    void SaveRGB16Tiff(TIFF* thetiff,int height, int width, byte* data, int page, int total );
    void SaveMonoTiff(TIFF* thetiff,int height, int width, byte* data, bool eightbit, int page, int total );

    //raw mode
    void DownsampleX(int height, int width, byte *src, byte *dest, bool eightbit, int factor);
    void BareTransform(int height, int width, byte* src,byte* dest, bool eightbit);
    void GenerateTransform(int height, int width, int parity);
    void ClearTransform();
    void IntializeFramebuffers();
    void ClearFramebuffers();
    int * SineTransform;


    int nBuffers;
    int nTriggerCount;

    //overlay
    void DrawOverlay();
    void SaveCurrentImageOverlay();
    bool bOverlay;
    bool bOvFramenumber;
    bool bOvCrosshairs;
    bool bOvScalebars;
    bool bOvPosition;
    bool bOvOverlayImage;
    bool bOvExposure;
    bool bChannelMerge;

    bool bBareTransform;

    bool bOvLiveGrid;

    bool bAppendPrev;

    //analysis
    bool bCompTraces;
    bool bCompHistograms;
    bool bCompGBRatio;

    //acquire preview
    bool bAcquirePreview;
    bool bSumAcquire;
    bool bLockADC;

    int roi_number;
    int roi_color;
    int roi_width;
    int roi_height;
    int roi_rows;
    int roi_columns;
    int roi_startx;
    int roi_starty;

    double dPositionMicrons[3];
    double dRotationDegrees;
    double dFOVXMicrons;
    double dFOVYMicrons;
    double dOVIntensity;

    QString sCurrentDCF;


    //void ModifyDCF(int height, int width);

    MIL_ID mSystem;
    MIL_ID mApplication;
    MIL_ID mDigitizer;
    MIL_ID mDisplay;
    MIL_ID mImageDisplay;

    MIL_ID mbDisplayBuffer;
    MIL_ID mbGrabBuffer[MAX_BUFFERS];
    MIL_ID mbCallbackProcessingBuffer[MAX_PROCESSING_BUFFERS];
    MIL_ID mbWarp[2];
    MIL_ID mbOverlay;


    long   mbGrabBufferSize;
    long   ProcessFrameCount;
    long   NbFrames;
    double ProcessFrameRate;

    HookDataStruct UserHookData;

    bool   bInitialized;

    bool   bMonitoring;
    bool   bAcquiring;
    bool   bSaveMonitor;
    bool   bTriggerOut;
    bool   bExtTrigger;
    bool   bRetrigger;
    bool   bStopTrigger;
    bool   bACCoupling;

    bool   bRawCProcessing;

    bool   bFragment;
    int    nFragmentSize;
    int    nCurrentFragment;

    //flags for callback structure
    //important redundancy for multithreading
    //to avoid race condition
    bool    bAcquire;
    bool    bFlipX;
    bool    bFlipY;
    bool    bFlipSlow;
    bool    bMeanConvolve;
    bool    bMedianConvolve;
    bool    bWarp;
    bool    bFlipRes;
    bool    bInvert;
    bool    bLog;
    bool    bMerge;
    bool    bColor;
    bool    bCopyChannel[4];
    bool    bSaveChannel[4];

    int     nSummationTotal;
    int     nHorizontalDownsample;
    int     mhz;

    //calculate dcf
    int     nDesiredLinesPerFrame;

    //calculate hsync
    int     nBaseClock;
    int     nBackPorch;
    int     nFrontPorch;
    int     nSync;
    int     nResonantFrequency;
    int     nClockMultiplier;

    int     nMissed;

    int     nAcquisitionNumber;

    int     nMin[4];
    int     nMax[4];
    double     dADCMax[4];
    double     dADCMin[4];


    QString sFilepath;
    QString sFilebase;
    QString sFilename;
    QString sFilenameChannel[4];
    int     nFile;
    int     nFramesPerFile;
    double  dFramerate;

    TIFF *mytiff[4];


};

#endif // MATROXIMAGINGLIBRARY_H
